package megrez.bussiness.system.web.rest;

import static org.springframework.util.StringUtils.hasText;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;
import megrez.bussiness.system.entity.Area;
import megrez.bussiness.system.repository.AreaRepository;
import megrez.bussiness.system.repository.AreaSpecification;
import megrez.bussiness.system.service.AreaService;
import megrez.bussiness.system.web.dto.AreaDto;
import megrez.bussiness.system.web.mapper.AreaMapper;

/**
 * 地区接口
 * 
 * @author Lucky Yang
 * @since 0.0.1
 */
@RestController
@RequestMapping("/v1/areas")
@RequiredArgsConstructor
public class AreaResource {
    private final AreaRepository areaRepository;
    private final AreaService areaService;

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public String create(@RequestParam(name = "parentId", required = false) Long parentId,
            @RequestBody AreaDto areaDto) {
        Area entity = areaService.save(parentId, AreaMapper.INST.toEntity(areaDto));
        return entity.getId().toString();
    }

    @PutMapping("/{id}")
    public void update(@PathVariable("id") Long id, @RequestBody AreaDto areaDto) {
        areaService.update(id, AreaMapper.INST.toEntity(areaDto));
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void delete(@PathVariable("id") Long id) {
        areaService.delete(id);
    }

    @GetMapping("/code-name")
    public Map<String, String> getCodeName() {
        return areaService.getCodeNameMap();
    }

    @GetMapping("/list")
    public List<AreaDto> get(@RequestParam(name = "onlyTop", required = false) Boolean onlyTop,
            @RequestParam(name = "name", required = false) String name) {
        Specification<Area> where = Specification
                .where(Boolean.TRUE.equals(onlyTop) ? AreaSpecification.parentIsNull() : null)
                .and(hasText(name) ? AreaSpecification.nameLike(name) : null);

        List<Area> entities = areaRepository.findAll(where);
        Collections.sort(entities, Comparator.comparing(Area::getPathCode));
        return AreaMapper.INST.toDto(entities);
    }

    @GetMapping("/{id}/children")
    public List<AreaDto> getChildren(@PathVariable("id") Long id) {
        Area parent = areaService.findById(id);
        List<Area> entities = areaRepository.findByParent(parent);
        Collections.sort(entities, Comparator.comparing(Area::getCode));
        return AreaMapper.INST.toDto(entities);
    }

    @GetMapping("/{id}/grandchildren")
    public List<AreaDto> getGrandchildren(@PathVariable("id") Long id) {
        List<Area> entities = areaService.getGrandchildren(id);
        return AreaMapper.INST.toDto(entities);
    }

    @GetMapping("/{id}")
    public AreaDto getById(@PathVariable("id") Long id) {
        Area entity = areaService.findById(id);
        return AreaMapper.INST.toDto(entity);
    }
}
